/*--------------------------------------------------------------------------
Example.c
****************************************
**  Copyright  (C)    2021-2022   **
**  Web:              http://rothd.cn   **
****************************************
--------------------------------------------------------------------------*/

#include "../MC3172/MC3172.h"
#include <math.h>
#include "common.h"
#include "test_spi.h"
////////////////////////////////////////////////////////////

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

// RST码
#define TRST 0x00
// 0码
#define TOL 0x80
// 1码
#define TOH 0xf8

// 演示时间
#define DELAY_US_NUM 300000

// 每灯珠bit位数
#define R_BYTE_BITS 24

// 灯珠数量
#define R_NUM 24

// 所有灯珠对应的bit位数
#define R_NUM_BITS R_NUM * R_BYTE_BITS

// RST位发送的个数
#define R_NUM_RESET_BITS 50

// G=0 R=0 B=0对应数据
unsigned char default_tx0[] = {
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL};

// G=0b10000000 R=0b10000000 B=0b10000000对应数据
unsigned char default_tx1[] = {
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL};

// 多种颜色对应的部分数据
unsigned char default_tx1_colors[] [R_BYTE_BITS]= {
    {
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
    {
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
    {
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
    {
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
    {
    TOH, TOH, TOH, TOH, TOH, TOH, TOH, TOH,
    TOH, TOH, TOH, TOH, TOH, TOH, TOH, TOH,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
    {
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
    {
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOL, TOL, TOL, TOL, TOL, TOL, TOL, TOL,
    TOH, TOL, TOL, TOL, TOL, TOL, TOL, TOL},
};

void GPCOM_SPI_WS2812B2(u32 gpcom_sel)
{
    INTDEV_SET_CLK_RST(gpcom_sel,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV2));

    GPCOM_SET_IN_PORT(gpcom_sel,(GPCOM_MASTER_IN_IS_P3));
    GPCOM_SET_OUT_PORT(gpcom_sel,( \
            GPCOM_P0_OUTPUT_ENABLE|GPCOM_P1_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_ENABLE|GPCOM_P3_OUTPUT_DISABLE| \
            GPCOM_P0_IS_HIGH|      GPCOM_P1_IS_MASTER_CLK|GPCOM_P2_IS_MASTER_OUT|GPCOM_P3_IS_HIGH
                      ));
    GPCOM_SET_COM_MODE(gpcom_sel,(GPCOM_SPI_MASTER_MODE3|GPCOM_TX_MSB_FIRST|GPCOM_RX_MSB_FIRST));
    
    // 设置SPI外设时钟，数据发送速度
    GPCOM_SET_COM_SPEED(gpcom_sel,CORE_CLOCK_HZ/INTDEV_CLK_IS_CORECLK_DIV2, 6400000);


    while(!(GPCOM_TX_FIFO_EMPTY(gpcom_sel))){};
    GPCOM_SET_OVERRIDE_GPIO(gpcom_sel, ( \
            GPCOM_P0_OVERRIDE_GPIO| \
            GPCOM_P1_OVERRIDE_GPIO| \
            GPCOM_P2_OVERRIDE_GPIO| \
            GPCOM_P3_OVERRIDE_GPIO|GPCOM_P3_INPUT_ENABLE  \
                                              ));

    u32 t = 0;

    // 发送缓冲区
    unsigned char default_tx[R_NUM_BITS+R_NUM_RESET_BITS*2+10];
    while(1){
        u16 idx = 0;
        // RESET Bits
        for(u16 n=0;n<R_NUM_RESET_BITS;n++) {
            default_tx[idx++] = TRST;
        }

        // 驱动灯珠
        for(u16 m=0;m<R_NUM;m++) {
            if(t%R_NUM==m) {
                for(u16 n=0;n<R_BYTE_BITS;n++) {
                    default_tx[idx++] = default_tx1_colors[m%7][n];
                }
            } else {
                for(u16 n=0;n<R_BYTE_BITS;n++) {
                    default_tx[idx++] = default_tx0[n];
                }
            }
        }

        // RESET Bits
        for(u16 n=0;n<R_NUM_RESET_BITS;n++) {
            default_tx[idx++] = TRST;
        }        

        // 设置输出
        GPCOM_SET_OUT_PORT(gpcom_sel,( \
                GPCOM_P0_OUTPUT_ENABLE|GPCOM_P1_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_ENABLE|GPCOM_P3_OUTPUT_DISABLE| \
                GPCOM_P0_IS_HIGH|      GPCOM_P1_IS_MASTER_CLK| GPCOM_P2_IS_MASTER_OUT|GPCOM_P3_IS_HIGH
                            ));

        // 写入输出缓冲区
        for(u16 n=0;n<idx;n++) {
            while(GPCOM_TX_FIFO_FULL(gpcom_sel));
            GPCOM_PUSH_TX_DATA(gpcom_sel,default_tx[n]);
        }        
        while(!(GPCOM_TX_FIFO_EMPTY(gpcom_sel))){};

        // 设置输出引脚低电平
        GPCOM_SET_OUT_PORT(gpcom_sel,( \
                GPCOM_P0_OUTPUT_ENABLE|GPCOM_P1_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_ENABLE|GPCOM_P3_OUTPUT_DISABLE| \
                GPCOM_P0_IS_HIGH|      GPCOM_P1_IS_MASTER_CLK| GPCOM_P2_IS_LOW|GPCOM_P3_IS_HIGH
                            ));

        delay_us(DELAY_US_NUM);
        t++;
    }

    GPCOM_SET_OUT_PORT(gpcom_sel,( \
            GPCOM_P0_OUTPUT_ENABLE|GPCOM_P1_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_ENABLE|GPCOM_P3_OUTPUT_DISABLE| \
            GPCOM_P0_IS_HIGH|      GPCOM_P1_IS_MASTER_CLK| GPCOM_P2_IS_MASTER_OUT|GPCOM_P3_IS_HIGH
                        ));
}

////////////////////////////////////////////////////////////
